<?php

/**
 * @user magein
 * @date 2023/12/1 15:48
 */

namespace magein\think\command\traits;

use magein\utils\Console;
use magein\utils\File;
use magein\utils\Result;
use magein\utils\Variable;
use think\db\exception\DbException;
use think\facade\Db;

trait CommandParamParse
{
    /**
     * 获取模型的命名空间
     * @param $name
     * @return  string|null
     */
    public function modelNamespace($name): ?string
    {
        $config = app()->config->get('console.config.model', []);

        $path = ($config['path'] ?? '') ?: 'app/model';

        $names = explode('/', $name);
        $filename = array_pop($names);
        $filepath = trim($path, '/') . '/';
        foreach ($names as $item) {
            $filepath .= Variable::camelCase($item) . '/';
        }
        $filepath .= Variable::pascal(trim($filename, '/')) . '.php';

        $namespace = preg_replace(['/\.\/app/', '/\.php/', '/\//'], ['app', '', '\\\\'], $filepath);

        if (class_exists($namespace)) {
            return $namespace;
        }

        return null;
    }

    /**
     * 实例化模型
     * @param $name
     * @return mixed|null
     */
    public function model($name)
    {
        $namespace = $this->modelNamespace($name);

        if (empty($namespace)) {
            return null;
        }

        return new $namespace();
    }

    /**
     * 匹配表名称
     * @param string $table_name
     * @return array
     */
    public function mapTable(string $table_name): array
    {
        // 获取所有的表
        $tables = Db::query("show tables");
        if (empty($tables)) {
            return [];
        }

        $maps = [];
        $key = 1;
        foreach ($tables as $item) {
            $n = current($item);
            if (preg_match('/^' . $table_name . '/', $n)) {
                $maps[$key] = $n;
                $key++;
            }
        }

        return $maps;
    }

    /**
     * 获取表名称
     * @param string $name
     * @param int $index 索引,从1开始
     * @return Result
     */
    public function tableAttrs(string $name, int $index = 0): Result
    {
        $maps = $this->mapTable($name);

        if (in_array($name, $maps)) {
            $table_name = $name;
        } elseif (count($maps) > 1) {
            if (empty($index)) {
                Console::eol();
                Console::blue('请使用-i参数进行选择:');
                Console::eol();
                foreach ($maps as $key => $item) {
                    Console::white('  ' . $key . ' : ' . $item);
                }
                return Result::error('');
            } else {
                $table_name = $maps[$index] ?? '';
            }
        } else {
            $table_name = $maps[1] ?? '';
        }

        if (empty($table_name)) {
            return Result::error("Map database table fail: 没有匹配到数据库{$name}表");
        }

        try {
            $attrs = Db::query("show full columns from $table_name");
        } catch (DbException $exception) {
            return Result::error("Map database table fail: 没有匹配到数据库{$name}表");
        }

        return Result::success(compact('table_name', 'attrs'));
    }

    /**
     * 获取保存文件路径不存在则创建
     * @param $name
     * @param $type
     * @param $default
     * @return string
     */
    public function filepath($name, $type, $default): string
    {
        $path = app()->config->get("console.config.$type.path", []);

        $path = $path ?: $default;

        $names = explode('/', $name);
        array_pop($names);
        $filepath = trim($path, '/') . '/';
        foreach ($names as $item) {
            $filepath .= Variable::camelCase($item) . '/';
        }

        if (!is_dir($filepath)) {
            mkdir($filepath, 0777, true);
        }

        return $filepath;
    }

    /**
     * 获取filename
     * @param $name
     * @param string $suffix
     * @return string
     */
    public function filename($name, string $suffix = ''): string
    {
        $names = explode('/', $name);
        $filename = array_pop($names);

        return Variable::camelCase($filename) . Variable::pascal($suffix);
    }

    /**
     * 根据文件名称获取命名空间
     * @param $filepath
     * @return string
     */
    public function namespace($filepath): string
    {
        // 文件的命名空间
        return str_replace('/', '\\', trim($filepath, '/'));
    }


    /**
     * 获取模型根据表名称
     * @param $table_name
     * @param $index
     * @return array|mixed|string|string[]
     */
    public function findModelByTableName($table_name, $index = null)
    {
        $config = $this->app->config->get('console.config.model', []);

        // 基本路径
        $base_path = $config['path'] ?? '' ?: 'app/model';

        $result = File::getTreeList($base_path);

        $table_name = Variable::pascal($table_name);

        $models = [];
        $key = 1;
        if ($file_list = $result->getData()) {
            foreach ($file_list as $file) {
                $filename = pathinfo($file, PATHINFO_FILENAME);
                if (preg_match('/' . $table_name . '/', $filename)) {
                    $model_name = pathinfo($file, PATHINFO_FILENAME);
                    $model_namespace = pathinfo($file, PATHINFO_DIRNAME) . '/' . $model_name;
                    $model_namespace = str_replace('/', '\\', $model_namespace);
                    $models[$key] = $model_namespace;
                    $key++;
                }
            }
        }

        if (!is_null($index)) {
            return $models[$index];
        }

        return $models;
    }
}